package qrcode

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"gitee.com/xlizy/common-go/base/enums/qrcode_type"
	"gitee.com/xlizy/common-go/utils/json"
	"gitee.com/xlizy/common-go/utils/zlog"
	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/qr"
	"github.com/fogleman/gg"
	"image"

	"image/color"
	"image/png"
	"os"
)

type QRCodeData struct {
	Type string `json:"type"`
	Data any    `json:"data"`
}

func GenQRCodeData(qrType qrcode_type.QRCodeType, data interface{}) QRCodeData {
	return QRCodeData{
		Data: data,
		Type: qrType.Enum(),
	}
}

func (d QRCodeData) GenImage(note string, size int, level qr.ErrorCorrectionLevel) image.Image {
	finalWidth := size
	finalHeight := size
	if note != "" {
		finalHeight = int(float64(size)/8.5 + float64(size))
	}
	qrCode, err := qr.Encode(json.ToJsonStr(d), level, qr.Auto)
	if err == nil {
		qrCode, err = barcode.Scale(qrCode, size, size)
		if err == nil {
			// 创建绘图上下文
			dc := gg.NewContext(finalWidth, finalHeight)
			// 绘制二维码
			dc.DrawImage(qrCode, 0, 0)

			dc.SetColor(color.White)
			dc.DrawRectangle(0, float64(size), float64(size), float64(size+30))
			dc.Fill()

			if note != "" {
				// 设置字体和颜色
				//if err = dc.LoadFontFace("./fonts/Arial.ttf", 20); err != nil {
				if err = dc.LoadFontFace("./fonts/JetBrainsMono-Light.ttf", 20); err != nil {
					zlog.Error("加载字体异常", err.Error())
				}
				dc.SetColor(color.Black)

				// 计算备注文本的宽度和高度
				tw, _ := dc.MeasureString(note)
				// 计算备注文本的绘制位置
				x := (float64(size) - tw) / 2
				y := float64(size) + float64(size)/8.5/2

				// 绘制备注文本
				dc.DrawString(note, x, y)
			}

			return dc.Image()
		}
	}
	return nil
}

func GenUrlQRImage(url, note string, size int, level qr.ErrorCorrectionLevel) image.Image {
	finalWidth := size
	finalHeight := size
	if note != "" {
		finalHeight = int(float64(size)/8.5 + float64(size))
	}
	qrCode, err := qr.Encode(url, level, qr.Auto)
	if err == nil {
		qrCode, err = barcode.Scale(qrCode, size, size)
		if err == nil {
			// 创建绘图上下文
			dc := gg.NewContext(finalWidth, finalHeight)
			// 绘制二维码
			dc.DrawImage(qrCode, 0, 0)

			dc.SetColor(color.White)
			dc.DrawRectangle(0, float64(size), float64(size), float64(size+30))
			dc.Fill()

			if note != "" {
				// 设置字体和颜色
				//if err = dc.LoadFontFace("./fonts/Arial.ttf", 20); err != nil {
				if err = dc.LoadFontFace("./fonts/JetBrainsMono-Light.ttf", 20); err != nil {
					zlog.Error("加载字体异常", err.Error())
				}
				dc.SetColor(color.Black)

				// 计算备注文本的宽度和高度
				tw, _ := dc.MeasureString(note)
				// 计算备注文本的绘制位置
				x := (float64(size) - tw) / 2
				y := float64(size) + float64(size)/8.5/2

				// 绘制备注文本
				dc.DrawString(note, x, y)
			}

			return dc.Image()
		}
	}
	return nil
}

func SaveToFile(img image.Image, path string) {
	// 打开文件准备写入
	file, err := os.Create(path)
	if err != nil {
		panic(err)
	}
	defer func(file *os.File) {
		_ = file.Close()
	}(file)

	_ = png.Encode(file, img)
}

func SaveToBase64(img image.Image) string {
	var buf bytes.Buffer
	_ = png.Encode(&buf, img)
	return fmt.Sprintf("data:image/png;base64,%s", base64.StdEncoding.EncodeToString(buf.Bytes()))
}
